package lib

import (
	"bufio"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"github.com/rs/xid"
	"github.com/spf13/viper"
	"gopkg.in/gomail.v2"
	"io"
	"manageCrontab/models"
	"os"
	"os/exec"
	"strconv"
	"time"
)

var DATETIME = time.Now().Format("2006-01-02 15:04:05")

// @title 三元表达式
func If(condition bool, trueVal, falseVal interface{}) interface{} {
	if condition {
		return trueVal
	}
	return falseVal
}

// @title 获取json返回信息
// @param code 状态
// @param data 返回数据
// @param msg 返回说明
func GetJsonResponse(code int, data interface{}, msg string) string {
	resp := models.ResponseJson{
		Code: code,
		Msg:  If(msg != "", msg, "SUCCESS").(string),
		T:    GetTimeStamp(""),
		Data: data,
	}
	respStr, err := json.Marshal(resp)
	if err != nil {
		panic(err)
	}
	return string(respStr)
}

func GetJsonResponse_(code int, data interface{}, msg string) []byte {
	resp := models.ResponseJson{
		Code: code,
		Msg:  If(msg != "", msg, "SUCCESS").(string),
		T:    GetTimeStamp(""),
		Data: data,
	}
	respStr, err := json.Marshal(resp)
	if err != nil {
		panic(err)
	}
	return respStr
}

// @title 获取时间戳， 如果datetime为空字符串则返回当前时间戳
// @param datetime 日期时间格式，传空字符串获取当前时间戳
func GetTimeStamp(datetime string) int64 {
	if len(datetime) > 0 {
		formatTime, err := time.Parse("2006-01-02 15:04:05", datetime)
		if err != nil {
			panic(err) //打印结果：2017-04-11 13:33:37 +0000 UTC
		}
		return formatTime.Unix()
	}
	return time.Now().Unix()
}

// @title 获取时间戳， 如果datetime为空字符串则返回当前时间戳
// @param timestamp  时间戳，为0获取当前时间
func GetDateTime(timestamp int64) string {
	if timestamp > 0 {
		return time.Unix(timestamp, 0).Format("2006-01-02 15:04:05")
	}
	return time.Now().Format("2006-01-02 15:04:05")
}

// @title 判断参数类型
func ParamType(param interface{}) string {
	switch param.(type) {
	case string:
		return "string"
	case int:
		return "int"
	case float64:
		return "float64"
	case []interface{}:
		return "array"
	case map[string]interface{}:
		return "map"
	default:
		return "unknow"
	}
}

// @title    获取唯一id
// @return    返回唯一id
func GendXid() string {
	id := xid.New()
	//fmt.Printf("github.com/rs/xid:           %s\n", id.String())
	return id.String()
}

// @title    发送邮件
// @param mailTo    发送给谁
// @param subject    发送标题
// @param body    发送主体
// @return    返回错误
func SendMail(mailTo []string, subject string, body string) error {
	//定义邮箱服务器连接信息，如果是阿里邮箱 pass填密码，qq邮箱填授权码
	mailConn := map[string]string{
		"user": "zibianqu@163.com",
		"pass": "",
		"host": "smtp.163.com",
		"port": "465",
	}

	port, _ := strconv.Atoi(mailConn["port"]) //转换端口类型为int

	m := gomail.NewMessage()
	m.SetHeader("From", "zibianqu"+"<"+mailConn["user"]+">") //这种方式可以添加别名，即“XD Game”， 也可以直接用<code>m.SetHeader("From",mailConn["user"])</code> 读者可以自行实验下效果
	m.SetHeader("To", mailTo...)                             //发送给多个用户
	m.SetHeader("Subject", subject)                          //设置邮件主题
	m.SetBody("text/html", body)                             //设置邮件正文

	d := gomail.NewDialer(mailConn["host"], port, mailConn["user"], mailConn["pass"])
	err := d.DialAndSend(m)
	fmt.Println("已发送", err)
	return err
}

func RecoverPanicLevel1() {
	if r := recover(); r != nil {
		//log.Panicf("Panic: %v", r)
		fmt.Println(r)
	}
}

func GetConfig() {
	fmt.Println(viper.Get("db"))
}
func inArray(search interface{}, arr []interface{}) {

}

// @title md5加密字符串
func Md5Str(str string) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(str)))
}

// @title 用法三：在命令位置使用并实时输出每行结果
func CmdAndChangeDirToShow(dir string, commandName string, params []string) error {
	cmd := exec.Command(commandName, params...)
	fmt.Println("CmdAndChangeDirToFile", dir, cmd.Args)
	//StdoutPipe方法返回一个在命令Start后与命令标准输出关联的管道。Wait方法获知命令结束后会关闭这个管道，一般不需要显式的关闭该管道。
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Println("cmd.StdoutPipe: ", err)
		return err
	}
	cmd.Stderr = os.Stderr
	cmd.Dir = dir
	err = cmd.Start()
	if err != nil {
		return err
	}
	//创建一个流来读取管道内内容，这里逻辑是通过一行一行的读取的
	reader := bufio.NewReader(stdout)
	//实时循环读取输出流中的一行内容
	for {
		line, err2 := reader.ReadString('\n')
		if err2 != nil || io.EOF == err2 {
			break
		}
		fmt.Println(line)
	}
	err = cmd.Wait()
	return err
}
